package com.xh.easyretry.strategy.retry;

import com.alibaba.fastjson.JSON;
import com.xh.easyretry.common.XHRetryContext;
import com.xh.easyretry.common.result.BaseResult;
import com.xh.easyretry.common.result.CommonResultCode;
import com.xh.easyretry.handler.ClassHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Objects;

import static com.xh.easyretry.common.XHRetryConstants.SYNC_STRATEGY;


@Slf4j
@Component
public class SyncRetryStrategy extends AbstractRetryStrategy {

    private final ClassHandler classHandler = ClassHandler.getInstance();

    @Override
    public String getStrategy() {
        return SYNC_STRATEGY;
    }

    @Override
    public Object execRetry(XHRetryContext retryContext) {
        Object result = null;
        while (canExecRetry(retryContext)) {
            final Integer currentRetryCount = retryContext.getCurrentRetryCount();
            Method method = retryContext.getMethod();
            try {
                log.info("act=SimpleRetryStrategy.execRetry msg=当前重试次数={} 开始重试", currentRetryCount);
                result = classHandler.processMethod(method, retryContext.getBean(), retryContext.getArgs());
                log.info("act=SimpleRetryStrategy.execRetry msg=当前重试次数={} 完成重试 result={}",
                        currentRetryCount, JSON.toJSONString(result));
                if (Objects.isNull(result)) {
                    return null;
                } else if (result instanceof BaseResult) {
                    if (((BaseResult) result).isSuccess()) {
                        return result;
                    }
                    if (!Objects.equals(((BaseResult) result).getCode(), CommonResultCode.NEED_RETRY_FAIL)) {
                        return result;
                    }
                }
                log.info("act=SimpleRetryStrategy.execRetry msg=当前重试次数={} 重试仍然失败", currentRetryCount);
                retryFailed(retryContext, result);
            } catch (Exception e) {
                log.error("act=SimpleRetryStrategy.execRetry msg=当前重试次数={} 重试时抛出异常", currentRetryCount, e);
                retryFailed(retryContext, result);
            }
        }
        if (Objects.nonNull(result)) {
            return result;
        }
        return buildResult(retryContext);
    }
}
